package com.websocketOfNotice;

import com.domain.IssueComment;
import com.domain.IssueCommentResponse;
import com.domain.IssueCommentResponseGrandson;
import com.mapper.helping.IssueCommentMapper;
import com.mapper.helping.IssueCommentResponseGrandsonMapper;
import com.mapper.helping.IssueCommentResponseMapper;
import com.util.UserUtil;
import com.websocketOfNotice.msgAnno.Notice;
import com.websocketOfNotice.msgDomain.NoticeType;
import living.com.result.ApiResult;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.lang.reflect.Method;



/**
 * <p>
 *     通知切面
 * </p>
 * @author 大忽悠
 * @create 2022/2/12 23:10
 */
@Component
@Aspect
@RequiredArgsConstructor
@Slf4j
public class NoticeAspect {
    private final InteractiveMessageService interactiveMessageService;
    private final IssueCommentResponseGrandsonMapper issueCommentResponseGrandsonMapper;
    private final IssueCommentResponseMapper issueCommentResponseMapper;
    private final IssueCommentMapper issueCommentMapper;

    /**
     * 只对controller包下的方法进行处理
     */
    @Pointcut("execution(public * com.controller.*.*(..))")
    public void point(){};

    /**
     * <p>通知处理</p>
     * @param joinPoint
     * @return
     */
    @Around("point()")
    @Transactional(value = "primaryTransactionManager")
    public Object noticeHandle(ProceedingJoinPoint joinPoint) throws Throwable {
        //方法先执行
        Object proceed = joinPoint.proceed();
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        //只处理方法上标注了notice注解的方法
        if(!method.isAnnotationPresent(Notice.class))
        {
            return proceed;
        }
        //获取注解里面的参数
        Notice notice = method.getAnnotation(Notice.class);
        //1.id索引
        int id_index = notice.id_index();
        Object[] parameters = joinPoint.getArgs();
        Assert.isTrue(id_index<=parameters.length,"notice注解中传入的id索引有误");
        Integer id;
        //默认为-1,只有COMMENT_ON_SON_OR_GRANTSON_COMMENT情况下,才为事件对应的用户id
        Integer u_id=-1;
        //特殊问题id
        Integer special_issue_id=-1;
        try{
            //儿子评论对应的id
            id = (Integer) parameters[id_index];
            //2.获取通知类型
            String notice_type = notice.notice_type();
            if(NoticeType.COMMENT_ON_SON_OR_GRANTSON_COMMENT.getType().equals(notice_type))
            {
                //返回的是孙子评论id
                ApiResult<Integer> apiResult = (ApiResult<Integer>) proceed;
                //需要判断当前孙子评论是回复指定儿子评论还是回复指定孙子评论
                IssueCommentResponseGrandson issueCommentResponseGrandson = issueCommentResponseGrandsonMapper.selectById(apiResult.getData());
                //获取孙子评论的toUserId
                Integer toUserId = issueCommentResponseGrandson.getToUserId();
                //获取问题id
                //回答的id
                Integer fatherCommentId = issueCommentResponseMapper.selectById(issueCommentResponseGrandson.getFatherCommentId()).getFatherCommentId();
                //找到问题的id
                special_issue_id=issueCommentMapper.selectById(fatherCommentId).getIssueId();
                //回复的儿子评论
                if(toUserId==0)
                {
                    //回复儿子评论--通知对应儿子评论的发布者
                    //id不用动,因为默认在此条件下,默认传入的应该就是儿子评论id
                    //获取儿子评论对应的用户id
                    IssueCommentResponse issueCommentResponse = issueCommentResponseMapper.selectById(id);
                    //判断子评论是否是匿名版主发布的评论
                    if(issueCommentResponse.getToUserId()!=0)
                    {
                        u_id=issueCommentResponse.getToUserId();
                    }
                    else
                    {
                        //查询出回答
                        IssueComment issueComment = issueCommentMapper.selectById(issueCommentResponse.getFatherCommentId());
                        u_id=issueComment.getUserId();
                    }
                }
                else if(toUserId==-1)
                {
                    //回复的匿名的孙子评论
                    //通知当前回答发布者
                    //如果儿子评论对应的toUserId不为0,那么toUserId就对应回答发布者用户id
                    IssueCommentResponse issueCommentResponse = issueCommentResponseMapper.selectById(id);
                    if(issueCommentResponse.getToUserId()!=0)
                    {
                        id=issueCommentResponse.getFatherCommentId();
                        u_id=issueCommentResponse.getToUserId();
                    }
                    else
                    {
                        //查询出回答
                        IssueComment issueComment = issueCommentMapper.selectById(issueCommentResponse.getFatherCommentId());
                        id=issueComment.getId();
                        u_id=issueComment.getUserId();
                    }
                }
                else
                {
                    //通知对应的孙子评论发布者
                    //这里孙子评论的toUserId是孙子评论对应的用户id
                    u_id=issueCommentResponseGrandson.getToUserId();
                    //查询出被回复的孙子评论对应的id
                    int grant_son_comment_id_index = notice.grant_son_comment_id_index();
                    Integer grantSonCommentId = (Integer) parameters[grant_son_comment_id_index];
                    if(grantSonCommentId==-1)
                    {
                        throw new IllegalArgumentException("请传入被回复的孙子评论对应的id");
                    }
                    id=grantSonCommentId;
                }
            }
            //当前用户,事件id,事件类型，事件关联用户id
            interactiveMessageService.notice(UserUtil.getUser(),id,notice_type,u_id,special_issue_id);
        }catch (Exception e)
        {
            throw new IllegalArgumentException("需要int类型,对应索引处参数类型有误");
        }
        return proceed;
    }

}
